// Copyright (c) 2011 SameGoal LLC.
// All Rights Reserved.
// Author: Andy Hochhaus <ahochhaus@samegoal.com>

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef NET_HTTP_SERVER_COMET_SESSION_H_
#define NET_HTTP_SERVER_COMET_SESSION_H_

#include <fcntl.h>
#include <gflags/gflags.h>
#include <glog/logging.h>

#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/thread/mutex.h"
#include "net/http/server/comet/request_helper.h"
#include "net/http/server/comet/timer_wrapper.h"
#include "net/http/server/comet/session_buffer.pb.h"

namespace sg {
namespace net {
namespace http {
namespace server {
namespace comet {

const std::string kIePadding = "7cca69475363026330a0d99468e88d23ce95e222591126"
    "443015f5f462d9a177186c8701fb45a6ffee0daf1a178fc0f58cd309308fba7e6f011ac38"
    "c9cdd4580760f1d4560a84d5ca0355ecbbed2ab715a3350fe0c479050640bd0e77acec90c"
    "58c4d3dd0f5cf8d4510e68c8b12e087bd88cad349aafd2ab16b07b0b1b8276091217a44a9"
    "fe92fedacffff48092ee693af\n";

class CometServer;

class Session {
 public:
  explicit Session(CometServer *server);

  void Write(const std::vector<std::string> &msg);
  void SetBackChannelRequest(es::Request *request);
  void OnBackChannelDisconnect();
  std::string GetSid();
  void Stop();
  void FlushBuffer(es::Request *request);

  uint64 last_array_id();
  bool back_channel_present();
  uint64 outstanding_back_channel_bytes();

 private:
  static char ToHexChar(uint8 value);

  void WriteInternal(const std::vector<std::string> &msg);
  void FlushBufferInternal(es::Request *request);
  void DropBufferToArrayId(const uint64 array_id);
  void SetupNoopCallback();
  void NoopCallback();

  es::Request *request_;
  TimerWrapper timer_event_;
  struct timeval last_back_channel_write_activity_, back_channel_start_;
  std::string type_;
  sg::base::thread::Mutex mutex_;

  // TODO(amarinph) move everything into the session buffer
  SessionBuffer session_buffer_;

  CometServer *server_;

  DISALLOW_COPY_AND_ASSIGN(Session);
};

}  // namespace comet
}  // namespace server
}  // namespace http
}  // namespace net
}  // namespace sg

#endif  // NET_HTTP_SERVER_COMET_SESSION_H_
